package com.unitedvision.service.impl;

import java.time.Month;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unitedvision.core.domain.Debitur;
import com.unitedvision.core.exception.ApplicationException;
import com.unitedvision.persistence.domain.CompanyCustomerEntity;
import com.unitedvision.persistence.domain.CompanyEntity;
import com.unitedvision.persistence.domain.OperatorEntity;
import com.unitedvision.persistence.domain.PaymentEntity;
import com.unitedvision.persistence.domain.PeriodeValue;
import com.unitedvision.persistence.repository.CompanyCustomerRepository;
import com.unitedvision.persistence.repository.CompanyRepository;
import com.unitedvision.persistence.repository.CustomerRepository;
import com.unitedvision.persistence.repository.OperatorRepository;
import com.unitedvision.persistence.repository.PaymentRepository;
import com.unitedvision.service.PaymentService;

@Service
public class PaymentServiceImpl implements PaymentService {

	@Resource
	private PaymentRepository paymentRepository;
	@Resource
	private OperatorRepository operatorRepository;
	@Resource
	private CustomerRepository customerRepository;
	@Resource
	private CompanyRepository companyRepository;
	@Resource
	private CompanyCustomerRepository companyCustomerRepository;
	
	@Transactional
	public void save(PaymentEntity paymentEntity) {
		paymentRepository.save(paymentEntity);
	}
	
	@Override
	@Transactional
	public void delete(PaymentEntity paymentEntity) {
		paymentRepository.delete(paymentEntity);
	}

	@Override
	public void pay(PaymentEntity payment) throws ApplicationException {
		if (payment.getCompany().getName().equals("United Technology")) {
			companyPay(payment);
		} else {
			privatePay(payment);
		}
	}
	
	private void privatePay(PaymentEntity paymentEntity) throws ApplicationException {
		CompanyEntity company = paymentEntity.getOperator().getCompany();
		
		if (!(company.isActive()))
			throw new ApplicationException("Company berstatus NONAKTIF");
		
		save(paymentEntity);
	}

	@Override
	@Transactional
	public void companyPay(PaymentEntity paymentEntity) throws ApplicationException {
		privatePay(paymentEntity);

		CompanyCustomerEntity companyCustomerEntity = paymentEntity.getCompanyCustomer();
		companyCustomerEntity.setDebt(checkDebt(companyCustomerEntity));
		companyCustomerRepository.save(companyCustomerEntity);
		
		CompanyEntity companyEntity = companyCustomerEntity.getCompany();
		companyRepository.save(companyEntity);
	}

	@Override
	public void update(PaymentEntity paymentEntity) {
		save(paymentEntity);
	}

	public PaymentEntity get(int id) {
		return paymentRepository.findOne(id);
	}

	@Override
	public List<PaymentEntity> getAll() {
		return paymentRepository.findAll();
	}

	@Override
	public List<PaymentEntity> getByPeriode(PeriodeValue periodeValue, CompanyEntity companyEntity) {
		return paymentRepository.findByPeriodeAndCompany(periodeValue, companyEntity);
	}

	@Override
	public List<PaymentEntity> getByOperator(OperatorEntity operatorEntity) {
		return paymentRepository.findByOperator(operatorEntity);
	}

	@Override
	public List<PaymentEntity> getByCompanyCustomer(CompanyCustomerEntity customerEntity) {
		return paymentRepository.findByCompanyCustomer(customerEntity);
	}

	@Override
	public List<PaymentEntity> getByCompany(CompanyEntity companyEntity) {
		return paymentRepository.findByCompany(companyEntity);
	}

	@Override
	public long count() {
		return paymentRepository.count();
	}

	public int checkDebt(Debitur debitur) {
		List<PaymentEntity> paymentEntities = paymentRepository.findByCompanyCustomer((CompanyCustomerEntity)debitur.getPayableCustomer());

		Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("GMT+8")));
		
		PeriodeValue last;
		if ((paymentEntities != null) && (paymentEntities.size() > 0)) {
			last = paymentEntities.get(paymentEntities.size() - 1).getPeriode();
		} else {
			calendar.setTime(debitur.getJoinDate());
			last = new PeriodeValue(calendar.get(Calendar.YEAR), Month.of(calendar.get(Calendar.MONTH) + 1));
		}
		
		int year = calendar.get(Calendar.YEAR);
		Month month = Month.of(calendar.get(Calendar.MONTH) + 1);
		
		return new PeriodeValue(year, month).compareTo(last);
	}
}
